iT邦幫忙

2023 iThome 鐵人賽

DAY 1
0
DevOps

Nix :為 Dev 與 Ops 而生的函數式軟體包管理器系列 第 1

[Day 01] 前言: Nix 心目中的相依管理

  • 分享至 

  • xImage
  •  

在開始講述 Nix 的細節之前,我們先來談談「為什麼要使用軟體包管理器、專案管理器」,我們期待軟體包管理器、專案管理器等部署工具能做到什麼,以及 Nix 如何回應這些需求。

從前從前

蠻荒之地

在一片蠻荒之地,專案程式碼散落在各自的目錄中,沒有軟體包管理也沒有專案管理。

編譯一個 C 語言程式專案,首先要 bootstrap 一個 C 編譯器,透過編譯器的路徑執行編譯,接著逐一指定所有原始碼與其他相依項 (dependencies) 的標頭檔與共享函式庫位置。想建置一個專案,必須先建置完所有相依專案和它們的相依專案。

終於建置、部署好整個作業系統發行版,幾個月已經過去了。

文明的曙光

為了自動化這些繁瑣的流程,首先要把檔案分門別類就定位,以便自動化尋找標頭檔和函式庫的位置。另外還需要一個系統來統一管理專案建置與安裝,只要指定一個要安裝的專案,就能自動建置、安裝相依的專案。

管理單一專案建置、尋找函式庫的工具發展成專案管理器 (project manager) ,而統一紀錄軟體建置流程與相依關係,並自動化安裝的工具就成為軟體包管理工具 (package manager) 。

不同檔案的放置方式隨著不同的系統、工具鍊而變化,但有了基本的共識才能跨平台使用專案;折衝尊俎之下, FHS (Filesystem Hierarchy Standard) 成為大部分 Linux 與其他類 UNIX 作業系統發行版開發者之間的共識。此外,許多專案管理器,支援以 GNU Coding Standards 當中的 安裝目錄變數 (Variables of Installation Directories) 指定安裝路徑。

Standard UNIX Filesystem Hierarchy

為了統一格式與節省安裝時間,軟體專案從直接安裝到系統目錄,變成先「安裝」到一個資料夾的特定相對位置,打包、運到使用者的電腦上後再放(部署)到系統目錄,於是有了「軟體包 (software packages) 」。

除了安裝程式之外,一個實用的軟體包管理器還要能「解除安裝軟體包與相關依賴項」的功能,做到基本的「回復至先前狀態」。另外還需要能更新特定的軟體包,使其他軟體包獲得功能的改善、錯誤修正與安全修正。

軟體包管理器很多時候也負責部份的設定,如暴露、調整環境變數,部署、修改設定檔等,將取用的軟體包整合到環境中。

複雜的現實

衝突

FHS 標準中,執行檔、標頭檔、函式庫分別集中放到系統目錄下,以方便引用。

但同名的檔案路徑相同,不同軟體包含有相同路徑的檔案軟體包彼此衝突。這常導致無法同時安裝兩個版本的函式庫,連帶導致依賴不同版本函式庫的軟體包互相衝突。

帶有不同修補 (patch) 或不同建置設定 (build configuration) 的軟體包也會因此衝突,造成修改過的軟體包礙於系統程式而無法安裝。幫名字加上後綴是常見的變通方法,但若希望依賴它的軟體包能使用修改後的依賴項,則必須新建一個軟體包並加上名字後綴,這樣的修改會一路傳遞到我們主要想使用的軟體包。

不要問我從哪裡來

「從共享目錄取得執行檔、函式庫」的預設行為,很難控制、判斷應用程式所使用的函式庫、執行檔來源。這造成同樣的程式移至另一臺電腦,便可能存取到不一樣的函式庫或執行檔,甚至可能存取不到。

因為環境差異造成的程式行為改變或報錯,往往難以除錯,成為「在我的電腦上會動!」 ("It works on my machine!") 的無奈。

能重現嗎?

還記得在電腦上總共裝過哪些軟體、調過哪些設定嗎?重灌時、到達新的電腦上,能夠再裝回同樣的環境嗎?

建置專案時,使用的相依項分別是哪些版本、用什麼參數設置?做了哪些修補?編譯時的環境變數有哪些?再建置一次,會是一樣的東西嗎?

問題的癥結與 Nix 的解方

上述的問題,能歸結於

  • 不同的東西佔用了相同的路徑
  • 程式存取到不該存取的東西
  • 建置的資訊沒有被完整的紀錄

如果我們能

  • 完整的紀錄建置資訊
  • 以建置資訊決定軟體包的路徑,把不同的東西放在不同的地方
  • 建置時指定能存取的依賴項、控制整個環境

就能解決這些問題。

Nix 部署系統如何描述與建置軟體包:

  • 求值 (evaluation) 階段:
    • 以自帶的函數程式語言 Nix language 描述所有準備部署的項目,包括每個軟體包、開發環境甚至整個作業系統、伺服器叢集。
    • 以 Nix language 所描述的建置資訊,在 Nix store 目錄下建立一個文字檔 (store derivation) ,供建置程式讀取。
    • 以建置資訊的雜湊值決定 store derivation 與軟體包建置結果 (output path) 的路徑。
    • 將軟體包的建置資訊以「軟體包實例」的形式傳入依賴於這個軟體包的建置函數,以產生依賴於它的軟體包。
  • 實現 (realization) 階段:
    • 用計算出來的雜湊值,到信任的 binary caches (建置結果提供來源,一般是某個線上建置農場 (build farm) ,如 Cachix ) 去找預先建置好的結果。有找到就直接下載下來。
    • 如果沒找到,或建置資訊中要求禁用 binary substitutes ,則在本機上開始建置。
    • 在支援的系統上,預設於 chroot 沙盒內建置,限制環境變數、網路、頂層目錄的存取,使 store derivaiton 紀錄的建置資訊儘可能控制建置結果。
  • 軟體包的更改(客製化)
    • 程式中的物件及磁碟上的建置結果都不會被更動。
    • 針對某個軟體包的「修改」將產生新的軟體包,有新的路徑。
    • 依賴它的軟體包也都會有對應的新軟體包。

Nix evaluation steps


下一篇
[Day 02] 取得與架設 Nix
系列文
Nix :為 Dev 與 Ops 而生的函數式軟體包管理器2
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言